package com.training.net;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

import com.google.gson.Gson;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.Logger;
import com.training.bean.AppVersion;
import com.training.bean.Course;
import com.training.bean.CourseContent;
import com.training.bean.CourseStage;
import com.training.bean.Feedback;
import com.training.bean.LearningTrackData;
import com.training.bean.User;
import com.training.utils.KeyStoreManager;
import com.training.utils.MD5Util;
import com.training.utils.RSAUtil;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class DataCenter {
    private Context mContext;
    private QueryInterface service;
    private static volatile DataCenter instance;

    private User user;
    private SharedPreferences shared;
    private OkHttpClient client;
    public String aesKey;
    public static DataCenter instance() {
        if (instance == null) {
            synchronized (DataCenter.class) {
                if (instance == null) {
                    instance = new DataCenter();
                }
            }
        }
        return instance;
    }

    public void onCreate(Context context) {
        mContext = context;

        shared = initSharedPreferences(context);
        initNet();
        Logger.addLogAdapter(new AndroidLogAdapter());
        try {
            KeyStoreManager.generateRSAKeyPairIfNotExists(context);
        } catch (Exception e) {
            Logger.e("Failed to generate RSA key pair", e);
        }
        createUserInfo();

    }

    private void initNet() {
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(1000);
        dispatcher.setMaxRequestsPerHost(1000);
        client = new OkHttpClient.Builder()
                .dispatcher(dispatcher)
                .addInterceptor(new NetInterceptor())
                .addInterceptor(new LoggingInterceptor())
                .retryOnConnectionFailure(false)
                .connectTimeout(Constant.CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .build();

        service = new Retrofit.Builder()
                .baseUrl(Constant.DEV_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build().create(QueryInterface.class);
    }

    private SharedPreferences initSharedPreferences(Context context) {
        try {
            String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
            return EncryptedSharedPreferences.create(
                    "secret_shared_prefs",
                    masterKeyAlias,
                    context,
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
        } catch (Exception e) {
            return null;
        }
    }

    //初始化用户信息 初始化各种
    private void createUserInfo() {
        String loginJson = shared.getString("UserInfo", "");
        if (!TextUtils.isEmpty(loginJson)) {
            user = new Gson().fromJson(loginJson, User.class);
            uploadPublicKey();
        }
    }

    public void setUser(User userBean) {
        user = userBean;
        saveUser();
    }
    public void clearUserInfo() {
        user = null;
        shared.edit().putString("UserInfo", "").apply();
    }

    private void saveUser() {
        if (user != null) {
            shared.edit().putString("UserInfo", new Gson().toJson(user)).apply();
            getEncryptedAESKey();
        }
    }

    public User getUser() {
        return user;
    }

    public void login(String username, String password, Callback<HttpResponse<User>> callback) {
        password= MD5Util.encrypt(password);
        Call<HttpResponse<User>> query = service.login(username, password);
        query.enqueue(callback);
    }
    public void getAllStage(Callback<HttpResponse<ArrayList<CourseStage>>> callback) {
        Call<HttpResponse<ArrayList<CourseStage>>> query = service.getAllStage();
        query.enqueue(callback);
    }
    public void getAllCourse(int stageId, Callback<HttpResponse<ArrayList<Course>>> callback) {
        Call<HttpResponse<ArrayList<Course>>> query = service.getAllCourse(stageId);
        query.enqueue(callback);
    }
    public void getAllCourseContent(int ccid,Callback<HttpResponse<ArrayList<CourseContent>>> callback) {
        Call<HttpResponse<ArrayList<CourseContent>>> query = service.getAllCourseContent(ccid);
        query.enqueue(callback);
    }

    public void getUserCollect(Callback<HttpResponse<ArrayList<Course>>> callback) {
        Call<HttpResponse<ArrayList<Course>>> query = service.getUserCollect();
        query.enqueue(callback);
    }
    public void collect(int cid,Callback<HttpResponse<String>> callback) {
        Call<HttpResponse<String>> query = service.collect(cid);
        query.enqueue(callback);
    }
    public void addFeedback(String content,Callback<HttpResponse<Feedback>> callback) {
        Call<HttpResponse<Feedback>> query = service.addFeedback(content);
        query.enqueue(callback);
    }
    public void checkVersion(Callback<HttpResponse<AppVersion>> callback) {
        Call<HttpResponse<AppVersion>> query = service.checkVersion();
        query.enqueue(callback);
    }
    public void uploadPublicKey() {
        try {
            PublicKey publicKey = KeyStoreManager.getPublicKey();
            if (publicKey == null) {
                Logger.e("Public key is null");
                return;
            }
            String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());

            Call<HttpResponse<String>> query = service.uploadPublicKey(publicKeyStr);
            query.enqueue(new NetCallback<HttpResponse<String>>() {
                @Override
                public void onError(int code, String message) {
                    // 处理失败
                    Logger.e("Failed to upload public key", message);
                }

                @Override
                public void onSuccess(HttpResponse<String> response) {
                    // 为这段代码:
                    try {
                        PrivateKey privateKey = KeyStoreManager.getPrivateKey();
                        // 直接使用私钥对象进行解密
                        byte[] decryptedData = RSAUtil.decryptData(response.data, privateKey);
                        aesKey = new String(decryptedData);
                    } catch (Exception e) {
                        Logger.e("Failed to decrypt AES key", e);
                    }
                }

                @Override
                public void onFinally() {

                }
            });
        } catch (Exception e) {
            Logger.e("Failed to upload public key", e);
        }
    }
    public void getEncryptedAESKey(){
        try {
            PrivateKey privateKey = KeyStoreManager.getPrivateKey();
            if (privateKey == null) {
                Logger.e("Private key is null");
                return;
            }
            Call<HttpResponse<String>> query = service.getEncryptedAESKey();
            query.enqueue(new NetCallback<HttpResponse<String>>() {
                @Override
                public void onError(int code, String message) {
                    Logger.e("Failed to upload public key", message);
                }

                @Override
                public void onSuccess(HttpResponse<String> response) {
                    try {
                        PrivateKey privateKey = KeyStoreManager.getPrivateKey();
                        // 直接使用私钥对象进行解密
                        byte[] decryptedData = RSAUtil.decryptData(response.data, privateKey);
                        aesKey = new String(decryptedData);
                    } catch (Exception e) {
                        Logger.e("Failed to decrypt AES key", e);
                    }
                }

                @Override
                public void onFinally() {

                }
            });
        } catch (Exception e) {
            Logger.e("Failed to get encrypted AES key", e);
        }

    }

    public void batchReport(ArrayList<LearningTrackData> learningTracks) {
        Call<HttpResponse<String>> query = service.batchReport(learningTracks);
        query.enqueue(new NetCallback<HttpResponse<String>>() {
            @Override
            public void onError(int code, String message) {
                Logger.e("上报学习进度失败", message);
            }

            @Override
            public void onSuccess(HttpResponse<String> response) {
                Logger.d("上报学习进度成功");
            }

            @Override
            public void onFinally() {

            }
        });
    }
}